package cn.easyutil.util.platform.wechat.pay;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.security.KeyStore;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;

import javax.net.ssl.SSLContext;

import cn.easyutil.util.platform.wechat.base.WeChatPayAccount;
import cn.easyutil.util.platform.wechat.base.WeChatPayStatus;
import cn.easyutil.util.platform.wechat.pay.bean.*;
import org.apache.http.Consts;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.util.EntityUtils;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;

import cn.easyutil.util.javaUtil.JsonUtil;
import cn.easyutil.util.javaUtil.LoggerUtil;
import cn.easyutil.util.javaUtil.StringUtil;
import cn.easyutil.util.javaUtil.HttpUtil;
import cn.easyutil.util.javaUtil.XmlUtil;

/**
 * 微信支付执行类
 * @author spc
 *
 */
public class WeChatPayUtil {

	/** 微信支付结果的返回调用结果   成功返回SUCCESS*/
	protected static final String RETURN_CODE = "return_code";
	/** 微信支付结果的返回支付   成功返回SUCCESS*/
	protected static final String RESULT_CODE = "result_code";
	/** 微信回调返回的本地订单号*/
	protected static final String OUT_TRADE_NO = "out_trade_no";
	/** 微信回调返回的支付金额*/
	protected static final String TOTAL_FEE = "total_fee";
    /** 签名*/
	protected static final String SIGN = "sign";
    /** 随机字符串*/
	protected static final String RANDOMSTR = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";

	private WeChatPayAccount account;

	public WeChatPayUtil(WeChatPayAccount account){
		this.account = account;
	}
	/**
	 * 扫码支付
	 * @return
	 */
	public WeChatPayResultBean scannpay(WeChatPayParamsBean params){
		Map<String, String> map = h5AndApppay(params,"NATIVE",null,null);
		WeChatPayResultBean bean = new WeChatPayResultBean();
		bean.setCodeUrl(map.get("code_url"));
		return bean;
	}

	/**
	 * H5支付
	 * @return
	 */
	public WeChatPayResultBean h5pay(WeChatPayParamsBean params){
		Map<String, String> result =h5AndApppay(params,"MWEB",null,null);
		WeChatPayResultBean bean = new WeChatPayResultBean();
		bean.setPrepayId(result.get("prepay_id"));
		bean.setMwebUrl(result.get("mweb_url"));
		return bean;
	}
	
	/**
	 * 公众号支付
	 * @return
	 */
	public WeChatPayResultBean publicpay(WeChatPayParamsBean params){
		if(params==null || params.getOpenId()==null){
			throw new RuntimeException("缺少openid");
		}
		String time = (System.currentTimeMillis()+"").substring(0, 10);
		Map<String,String> result = h5AndApppay(params,"JSAPI",time,params.getOpenId());
		SortedMap<String, String> returnMap = new TreeMap<String, String>();
		returnMap.put("appId", this.account.getAppid());
		returnMap.put("timeStamp", time);
		returnMap.put("nonceStr", result.get("nonce_str"));
		returnMap.put("package", "prepay_id="+result.get("prepay_id"));
		returnMap.put("signType", "MD5");
		String sign = createSign(returnMap, this.account.getApiKey());
		returnMap.put("paySign", sign);
		WeChatPayResultBean bean = new WeChatPayResultBean();
		bean.setPrepayId(returnMap.get("appId"));
		bean.setTimeStamp(returnMap.get("timeStamp"));
		bean.setNoncestr(returnMap.get("nonceStr"));
		bean.setPackageValue(returnMap.get("package"));
		bean.setSignType(returnMap.get("signType"));
		bean.setPaySign(returnMap.get("paySign"));
		return bean;
	}
	
	/**
	 * app支付
	 * @return
	 */
	public WeChatPayResultBean apppay(WeChatPayParamsBean params){
		Map<String, String> result = h5AndApppay(params,"APP",null,null);
		SortedMap<String, String> returnMap = new TreeMap<String, String>();
		returnMap.put("appid", this.account.getAppid());
		returnMap.put("partnerid", this.account.getMchId());
		returnMap.put("prepayid", result.get("prepay_id"));
		returnMap.put("package", "Sign=WXPay");
		returnMap.put("noncestr", StringUtil.getRandomString(32));
		returnMap.put("timestamp", (System.currentTimeMillis()+"").substring(0, 10));
		String sign = createSign(returnMap, this.account.getApiKey());
		returnMap.put("sign", sign);
		returnMap.put("packageValue", returnMap.get("package"));
		WeChatPayResultBean bean = new WeChatPayResultBean();
		bean.setAppId(returnMap.get("appid"));
		bean.setPartnerId(returnMap.get("partnerid"));
		bean.setPrepayId(returnMap.get("prepayid"));
		bean.setPackageValue(returnMap.get("package"));
		bean.setNoncestr(returnMap.get("noncestr"));
		bean.setTimeStamp(returnMap.get("timestamp"));
		bean.setSign(returnMap.get("sign"));
		return bean;
	}
	
	/**
	 * H5和app的支付
	 * @return
	 */
	private Map<String,String> h5AndApppay(WeChatPayParamsBean params,String trade_type,String timestamp,String opernId){
		SortedMap<String, String> parameterMap = new TreeMap<String, String>();
        parameterMap.put("appid", this.account.getAppid());
        parameterMap.put("mch_id", this.account.getMchId());
        parameterMap.put("nonce_str", getRandomString(32));
        parameterMap.put("body", params.getBody());
        parameterMap.put("out_trade_no", params.getOrderNo());
        parameterMap.put("fee_type", "CNY");  

        parameterMap.put("total_fee", params.getTotalAmount()+"");
        parameterMap.put("spbill_create_ip", params.getAddress());
        parameterMap.put("notify_url", params.getNotifyUrl());
        parameterMap.put("trade_type", trade_type);
        parameterMap.put("sign_type", "MD5");

		parameterMap.put("attach", params.getAttach());
        if(timestamp!=null){
        	parameterMap.put("timeStamp", timestamp);
        }
        if(opernId != null){
        	parameterMap.put("openid", opernId);
        }
        String sign = createSign("UTF-8", parameterMap,this.account.getApiKey());
        parameterMap.put(SIGN, sign);
        String requestXML = getRequestXml(parameterMap);
        LoggerUtil.info(WeChatPayUtil.class,"统一下单封装参数"+requestXML);
        String result = HttpUtil.doUrl(
                "https://api.mch.weixin.qq.com/pay/unifiedorder", "POST",null,requestXML);
        SortedMap<String, String> map = null;
        try {  
            map = xmlToMap(result);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        //回调结果 
        String return_code = map.get(RETURN_CODE);
        if(!return_code.equals("SUCCESS")){
        	LoggerUtil.info(WeChatPayUtil.class,"微信支付状态码异常:"+result);
        	throw new RuntimeException("微信支付状态码异常:"+result);
        }
        //支付结果 成功为SUCCESS
        String result_code = map.get(RESULT_CODE);
        if(!result_code.equals("SUCCESS")){
        	LoggerUtil.info(WeChatPayUtil.class,"微信返回支付失败:",result);
        	throw new RuntimeException("微信返回支付失败:"+result);
        }
        if(timestamp!=null){
        	map.put("timeStamp", timestamp);
        }
        return map;
	}
	
	/**
	 * 企业付款到用户余额(请至官网查询注意事项)
	 * @param param
	 * @param certInput	微信证书路径
	 * @return
	 */
	public WeChatPayToUserResultBean payToUser(WeChatPayToUserParamBean param, InputStream certInput){
		SortedMap<String, String> parameters = new TreeMap<String, String>();
		// 参数：开始生成第一次签名
        parameters.put("appid", this.account.getAppid());
        parameters.put("mch_id", this.account.getMchId());
        parameters.put("partner_trade_no", param.getOrderNo());
        parameters.put("nonce_str", getRandomString(32));
        parameters.put("openId", param.getOpenId());
        if(param.isCheckName()){
        	parameters.put("checkName", "FORCE_CHECK");
        	parameters.put("re_user_name", param.getRealName());
        }else{
        	parameters.put("checkName", "NO_CHECK");
        }
        parameters.put("amount", param.getAmount()+"");
        parameters.put("spbill_create_ip", param.getIpAddress());
        parameters.put("desc", param.getBody());
        String sign = createSign(parameters, this.account.getApiKey());
        parameters.put("sign", sign);
        String requestXML = getRequestXml(parameters);
        LoggerUtil.info(WeChatPayUtil.class, "微信企业付款至用户零钱，封装参数:"+requestXML);
        String result = doHttps("https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers",requestXML,certInput);
        LoggerUtil.info(WeChatPayUtil.class, "微信企业付款至用户零钱，响应结果:"+result);
        WeChatPayToUserResultBean parseBean = JsonUtil.mapToBean(XmlUtil.xmlToMap(result), WeChatPayToUserResultBean.class);
        if(!StringUtil.isEmpty(parseBean.getReturn_code()) && !parseBean.getReturn_code().equals("SUCCESS")){
        	throw new RuntimeException("微信企业付款至用户零钱请求失败:"+result);
        }
        if(!StringUtil.isEmpty(parseBean.getResult_code()) && !parseBean.getResult_code().equals("SUCCESS")){
        	if(!StringUtil.isEmpty(parseBean.getErr_code()) && !parseBean.getErr_code().equals("SYSTEMERROR")){
        		throw new RuntimeException("微信企业付款至用户零钱请求失败:"+result);
        	}
        }
        return parseBean;
	}
	
	/**
	 * 企业付款至银行卡(请至官网查询注意事项)
	 * @param param
	 * @param certInput
	 * @return
	 */
	public WeChatPayToBankResultBean payToBank(WeChatPayToBankParamBean param, InputStream certInput){
		SortedMap<String, String> parameters = new TreeMap<String, String>();
		// 参数：开始生成第一次签名
        parameters.put("mch_id", this.account.getMchId());
        parameters.put("partner_trade_no", param.getOrderNo());
        parameters.put("nonce_str", getRandomString(32));
        parameters.put("enc_bank_no", param.getBankCardNo());
        parameters.put("enc_true_name", param.getRealName());
        parameters.put("bank_code", param.getBankCode());
        parameters.put("amount", param.getAmount()+"");
        String sign = createSign(parameters, this.account.getApiKey());
        parameters.put("sign", sign);
        String requestXML = getRequestXml(parameters);
        LoggerUtil.info(WeChatPayUtil.class, "微信企业付款至银行卡，封装参数:"+requestXML);
        String result = doHttps("https://api.mch.weixin.qq.com/mmpaysptrans/pay_bank",requestXML, certInput);
        LoggerUtil.info(WeChatPayUtil.class, "微信企业付款至银行卡，响应结果:"+result);
        WeChatPayToBankResultBean parseBean = JsonUtil.mapToBean(XmlUtil.xmlToMap(result), WeChatPayToBankResultBean.class);
        if(!StringUtil.isEmpty(parseBean.getReturn_code()) && !parseBean.getReturn_code().equals("SUCCESS")){
        	throw new RuntimeException("微信企业付款至银行卡请求失败:"+result);
        }
        if(!StringUtil.isEmpty(parseBean.getResult_code()) && !parseBean.getResult_code().equals("SUCCESS")){
        	if(!StringUtil.isEmpty(parseBean.getErr_code()) && !parseBean.getErr_code().equals("SYSTEMERROR")){
        		throw new RuntimeException("微信企业付款银行卡请求失败:"+result);
        	}
        }
        return parseBean;
	}
	/**
	 * 查询企业付款至银行的交易状态(请至官网查询注意事项)
	 * @param orderNo
	 * @param certInput
	 */
	public void queryPayToBank(String orderNo,InputStream certInput){
		SortedMap<String, String> parameters = new TreeMap<String, String>();
		// 参数：开始生成第一次签名
        parameters.put("mch_id", this.account.getMchId());
        parameters.put("partner_trade_no", orderNo);
        parameters.put("nonce_str", getRandomString(32));
        String sign = createSign(parameters, this.account.getApiKey());
        parameters.put("sign", sign);
        String requestXML = getRequestXml(parameters);
        LoggerUtil.info(WeChatPayUtil.class, "查询微信企业付款至银行卡，封装参数:"+requestXML);
        String result = doHttps("https://api.mch.weixin.qq.com/mmpaysptrans/query_bank",requestXML, certInput);
        LoggerUtil.info(WeChatPayUtil.class, "查询微微信企业付款至银行卡，响应结果:"+result);
        //TODO 结果未解析
        
        
	}
	/**
	 * 查询企业付款至用户零钱的交易状态(请至官网查询注意事项)
	 * @param orderNo
	 * @param certInput
	 * @return
	 */
	public int queryPayToUser(String orderNo, InputStream certInput){
		SortedMap<String, String> parameters = new TreeMap<String, String>();
		// 参数：开始生成第一次签名
        parameters.put("mch_id", this.account.getMchId());
        parameters.put("appid", this.account.getAppid());
        parameters.put("partner_trade_no", orderNo);
        parameters.put("nonce_str", getRandomString(32));
        String sign = createSign(parameters, this.account.getApiKey());
        parameters.put("sign", sign);
        String requestXML = getRequestXml(parameters);
        LoggerUtil.info(WeChatPayUtil.class, "查询微信企业付款至用户零钱，封装参数:"+requestXML);
        String result = doHttps("https://api.mch.weixin.qq.com/mmpaymkttransfers/gettransferinfo",requestXML, certInput);
        LoggerUtil.info(WeChatPayUtil.class, "查询微微信企业付款至用户零钱，响应结果:"+result);
		Map<String, Object> map = JsonUtil.jsonToMap(result);
		if(!map.get("return_code").equals("SUCCESS")){
			throw new RuntimeException("查询付款到用户账户订单失败:"+result);
		}
		if(!map.get("result_code").equals("SUCCESS")){
			throw new RuntimeException("查询付款到用户账户订单失败:"+result);
		}
		String status = map.get("status").toString();
		if(status.equalsIgnoreCase("SUCCESS")){
			return 1;
		}else if(status.equalsIgnoreCase("FAILED")){
			return -1;
		}else if(status.equalsIgnoreCase("PROCESSING")){
			return 0;
		}
		return 0;
	}
	
	/**
	 * 微信支付订单查询
	 * @param orderNo	商户内部订单或微信支付订单二选一
	 * @param weChatTradeNo		商户内部订单或微信支付订单二选一
	 */
	public WeChatPayStatus query(String orderNo, String weChatTradeNo){
		SortedMap<String, String> parameters = new TreeMap<String, String>();
		// 参数：开始生成第一次签名
        parameters.put("mch_id", this.account.getMchId());
        parameters.put("appid", this.account.getAppid());
        if(!StringUtil.isEmpty(orderNo)){
        	parameters.put("out_trade_no", orderNo);
        }else if(!StringUtil.isEmpty(weChatTradeNo)){
        	parameters.put("transaction_id", weChatTradeNo);
        }
        parameters.put("nonce_str", getRandomString(32));
        String sign = createSign(parameters, this.account.getApiKey());
        parameters.put("sign", sign);
        String requestXML = getRequestXml(parameters);
        LoggerUtil.info(WeChatPayUtil.class, "查询支付订单，封装参数:"+requestXML);
        String result = HttpUtil.doUrl("https://api.mch.weixin.qq.com/pay/orderquery", "POST",null,requestXML);
        Map<String, Object> map = XmlUtil.xmlToMap(result);
        //回调结果 
        String return_code = map.get(RETURN_CODE).toString();
        if(!return_code.equals("SUCCESS")){
        	LoggerUtil.info(WeChatPayUtil.class,"查询微信支付状态码异常:"+result);
        	throw new RuntimeException("查询微信支付状态码异常:"+result);
        }
        //支付结果 成功为SUCCESS
        String result_code = map.get(RESULT_CODE).toString();
        if(!result_code.equals("SUCCESS")){
        	LoggerUtil.info(WeChatPayUtil.class,"查询微信支付返回失败:",result);
        	throw new RuntimeException("查询微信支付返回失败:"+result);
        }
		String trade_state = map.get("trade_state").toString();
        return WeChatPayStatus.parse(trade_state);
	}

	
	 //随机字符串生成  
    private String getRandomString(int length) { //length表示生成字符串的长度
        Random random = new Random();
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < length; i++) {
            int number = random.nextInt(RANDOMSTR.length());
            sb.append(RANDOMSTR.charAt(number));
        }
        return sb.toString();
    }
    
  //xml解析  
    @SuppressWarnings("rawtypes")
	private SortedMap<String, String> xmlToMap(String strxml) throws  IOException, JDOMException {
        strxml = strxml.replaceFirst("encoding=\".*\"", "encoding=\"UTF-8\"");
        if (null == strxml || "".equals(strxml)) {
            return null;
        }
        SortedMap<String, String> m = new TreeMap<String, String>();
        InputStream in = new ByteArrayInputStream(strxml.getBytes("UTF-8"));
        SAXBuilder builder = new SAXBuilder();
        Document doc = builder.build(in);
        Element root = doc.getRootElement();
        Iterator it = root.getChildren().iterator();
        while (it.hasNext()) {
            Element e = (Element) it.next();
            String k = e.getName();
            String v = "";
            List children = e.getChildren();
            if (children.isEmpty()) {
                v = e.getTextNormalize();
            } else {
                v = getChildrenText(children);
            }
            m.put(k, v);
        }
        //关闭流  
        in.close();
        return m;
    }
    
    @SuppressWarnings("rawtypes")
	private String getChildrenText(List children) {
        StringBuffer sb = new StringBuffer();
        if (!children.isEmpty()) {
            Iterator it = children.iterator();
            while (it.hasNext()) {
                Element e = (Element) it.next();
                String name = e.getName();
                String value = e.getTextNormalize();
                List list = e.getChildren();
                sb.append("<" + name + ">");
                if (!list.isEmpty()) {
                    sb.append(getChildrenText(list));
                }
                sb.append(value);
                sb.append("</" + name + ">");
            }
        }
        return sb.toString();
    }
    
    public String createSign(SortedMap<String, String> parameters, String apiKey){
    	return createSign("UTF-8", parameters, apiKey);
    }
    //生成签名  
    @SuppressWarnings("rawtypes")
	public String createSign(String characterEncoding, SortedMap<String, String> parameters, String apiKey) {
        StringBuffer sb = new StringBuffer();
        Set es = parameters.entrySet();
        Iterator it = es.iterator();
        while (it.hasNext()) {
            Map.Entry entry = (Map.Entry) it.next();
            String k = (String) entry.getKey();
            Object v = entry.getValue();
            if (null != v && !"".equals(v) && !SIGN.equals(k) && !"key".equals(k)) {
                sb.append(k + "=" + v + "&");
            }
        }
        sb.append("key=" + apiKey);
        String sign = null;
        try {
        	sign = StringUtil.toMD5(sb.toString(), characterEncoding).toUpperCase();
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
        return sign;
    }
    
    /**
     * 请求退款
     * @param out_trade_no	支付时传给微信的订单号
     * @param total_fee	退款金额（不能大于支付金额）
     * @param certInput 证书input流
     * @return	请求微信的结果
     */
    public WeChatRefundResultBean refund(String out_trade_no, String out_refund_no, int total_fee, int refund_fee, InputStream certInput){
    	SortedMap<String, String> m = new TreeMap<String, String>();
		m.put("appid", this.account.getAppid());
		m.put("mch_id", this.account.getMchId());
		m.put("nonce_str", StringUtil.getRandomString(32));
		m.put("out_trade_no", out_trade_no);
		m.put("out_refund_no", out_refund_no);
		m.put("total_fee", total_fee+"");
		m.put("refund_fee", refund_fee+"");
		m.put("op_user_id", this.account.getMchId());
		String sign = createSign(m, this.account.getApiKey());
		m.put("sign", sign);
		LoggerUtil.info(WeChatPayUtil.class, "请求微信退款时的参数="+m);
		String outputStr = getRequestXml(m);
		String result =  doHttps("https://api.mch.weixin.qq.com/secapi/pay/refund",outputStr,certInput);
		LoggerUtil.info(WeChatPayUtil.class, "微信退款返回内容="+result);
		Map<String, Object> map = XmlUtil.xmlToMap(result);
		if(map.containsKey("return_code") && map.get("return_code").equals("SUCCESS")){
			if(!map.containsKey("err_code")){
				return JsonUtil.mapToBean(map, WeChatRefundResultBean.class);
			}
			if(map.containsKey("err_code_des")) {
				throw new RuntimeException(map.get("err_code_des").toString());
			}
		}
		throw new RuntimeException("未知异常："+result);
    }
    
    /***
     * 微信退款回调处理类
     * @param notifyData	微信退款回调的参数
     * @return	解析后的map
     */
    public WeChatRefundResultBean parseRefundCallback(String notifyData) {
    	Map<String, Object> map = XmlUtil.xmlToMap(notifyData);
		if(map.containsKey("req_info")){
			String info = map.get("req_info").toString();
			String md5 = StringUtil.toMD5(this.account.getApiKey()).toLowerCase();
			String result = StringUtil.AESDecode(info, md5);
			Map<String, Object> parse = XmlUtil.xmlToMap(result);
			return JsonUtil.mapToBean(parse, WeChatRefundResultBean.class);
		}
		LoggerUtil.info(WeChatPayUtil.class,"微信退款回调缺少必要参数req_info，参数信息："+notifyData);
		throw new RuntimeException("微信退款回调缺少必要参数req_info，参数信息："+notifyData);
    }
    
    /** 
     * 请求退款  
     * @param outputStr 参数
     * @param certInput	证书地址(绝对路径)
     * @return	调用返回
     */
	@SuppressWarnings("deprecation")
	private String doHttps(String wechatUrl,String outputStr,InputStream certInput){
		try {
			KeyStore keyStore = KeyStore.getInstance("PKCS12");
			StringBuilder res = new StringBuilder("");
			//记载证书路径
			try {
				keyStore.load(certInput, this.account.getMchId().toCharArray());
			} finally {
				try {
					certInput.close();
				} catch (Exception e) {}
			}
			// mch_id
			SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, this.account.getMchId().toCharArray()).build();
			// Allow TLSv1 protocol only
			SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext, new String[] { "TLSv1" }, null,
					SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
			CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
			try {
				
				HttpPost httpost = new HttpPost(wechatUrl);
				httpost.addHeader("Connection", "keep-alive");
				httpost.addHeader("Accept", "*/*");
				httpost.addHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
				httpost.addHeader("Host", "api.mch.weixin.qq.com");
				httpost.addHeader("X-Requested-With", "XMLHttpRequest");
				httpost.addHeader("Cache-Control", "max-age=0");
				httpost.addHeader("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0) ");
				StringEntity entity2 = new StringEntity(outputStr, Consts.UTF_8);
				httpost.setEntity(entity2);
				CloseableHttpResponse response = httpclient.execute(httpost);
				
				try {
					HttpEntity entity = response.getEntity();
					if (entity != null) {
						BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(entity.getContent()));
						String text = "";
						res.append(text);
						while ((text = bufferedReader.readLine()) != null) {
							res.append(text);
						}
					}
					EntityUtils.consume(entity);
				} finally {
					response.close();
				}
			} finally {
				httpclient.close();
			}
			return res.toString();
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}
    
  //请求xml组装  
    @SuppressWarnings("rawtypes")
	private static String getRequestXml(SortedMap<String, String> parameters) {
        StringBuffer sb = new StringBuffer();
        sb.append("<xml>");
        Set es = parameters.entrySet();
        Iterator it = es.iterator();
        while (it.hasNext()) {
            Map.Entry entry = (Map.Entry) it.next();
            String key = (String) entry.getKey();
            String value = (String) entry.getValue();
            if ("attach".equalsIgnoreCase(key) || "body".equalsIgnoreCase(key) || "sign".equalsIgnoreCase(key)) {
                sb.append("<" + key + ">" + "<![CDATA[" + value + "]]></" + key + ">");
            } else {
                sb.append("<" + key + ">" + value + "</" + key + ">");
            }
        }
        sb.append("</xml>");
        return sb.toString();
    }
    
    
    /**
     * 根据微信回调封装回调信息，并验证签名的正确性
     * @return
     */
	public WeChatPayCallBackParseBean getCallBackData(String callBackData){
    	try {
    		return getCallBackData(xmlToMap(callBackData));
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
    }
    
    /**
     * 验证回调签名
     * @return
     */
    @SuppressWarnings("rawtypes")
	private WeChatPayCallBackParseBean getCallBackData(Map<String, String> map){
        String charset = "utf-8";
        String signFromAPIResponse = map.get(SIGN);
        if (signFromAPIResponse == null || signFromAPIResponse.equals("")) {
        	LoggerUtil.info(WeChatPayUtil.class,"未发现回调数据中的签名");
            throw new RuntimeException("未发现回调数据中的签名");
        }
        LoggerUtil.info(WeChatPayUtil.class,"服务器回包里面的签名是:" + signFromAPIResponse);
        //过滤空 设置 TreeMap
        SortedMap<String, String> packageParams = new TreeMap<>();
        for (String parameter : map.keySet()) {
            String parameterValue = map.get(parameter);
            String v = "";
            if (null != parameterValue) {
                v = parameterValue.trim();
            }
            packageParams.put(parameter, v);
        }

        StringBuffer sb = new StringBuffer();
        Set es = packageParams.entrySet();
        Iterator it = es.iterator();
        while (it.hasNext()) {
            Map.Entry entry = (Map.Entry) it.next();
            String k = (String) entry.getKey();
            String v = (String) entry.getValue();
            if (!SIGN.equals(k) && null != v && !"".equals(v)) {
                sb.append(k + "=" + v + "&");
            }
        }
        sb.append("key=" + this.account.getApiKey());

        //将API返回的数据根据用签名算法进行计算新的签名，用来跟API返回的签名进行比较

        //算出签名
        String resultSign = "";
        String tobesign = sb.toString();
        if (null == charset || "".equals(charset)) {
            try {
				resultSign = StringUtil.toMD5(tobesign, charset).toUpperCase();
			} catch (Exception e) {
				LoggerUtil.error(WeChatPayUtil.class, e);
				throw new RuntimeException(e);
			}
        } else {
            try {
				resultSign = StringUtil.toMD5(tobesign, charset).toUpperCase();
			} catch (Exception e) {
				LoggerUtil.error(WeChatPayUtil.class, e);
				throw new RuntimeException(e);
			}
        }
        String tenpaySign = packageParams.get(SIGN).toUpperCase();
        if(!tenpaySign.equals(resultSign)){
        	LoggerUtil.info(WeChatPayUtil.class,"微信返回的签名与本机生成的不一致");
        	throw new RuntimeException("微信返回的签名与本机生成的不一致");
        }
        LoggerUtil.info(WeChatPayUtil.class,"微信回调返回信息:"+map);
        if(!map.get(RETURN_CODE).equals("SUCCESS")){
        	LoggerUtil.info(WeChatPayUtil.class,"微信回调返回支付失败,返回参数为:"+map);
        	throw new RuntimeException("支付失败");
        }
        if(!map.get(RESULT_CODE).equals("SUCCESS")){
        	LoggerUtil.info(WeChatPayUtil.class,"微信回调返回支付失败,返回参数为:"+map);
        	throw new RuntimeException("支付失败");
        }
        String json = JsonUtil.beanToJson(map);
        return JsonUtil.jsonToBean(json, WeChatPayCallBackParseBean.class);
    }
    
    //回复微信
    public String returnMessage(){
    	return "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";
    }
    
}
